package com.lhh.userservice.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lhh.springcommon.annotation.WebLog;
import com.lhh.springcommon.config.AliyunSmsProperties;
import com.lhh.springcommon.entity.User;
import com.lhh.springcommon.entity.vo.UserVO;
import com.lhh.springcommon.exception.CustomException;
import com.lhh.springcommon.service.*;
import com.lhh.springcommon.utils.CodeEnum;
import com.lhh.springcommon.utils.DataEncryption;
import com.lhh.springcommon.utils.SendSms;
import com.lhh.springcommon.interceptor.JwtInterceptor;
import com.lhh.userservice.service.UserManagementService;
import com.lhh.springcommon.utils.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;

/**
 * @author 李厚航
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class UserManagementServiceImpl implements UserManagementService {

    private final IUserService userService;

    private final JwtUtil jwtUtil;

    private final CacheManager cacheManager;

    @Value("${introduction}")
    private String defaultIntroduction;

    @Value("${avatar_url}")
    private String defaultAvatarUrl;

    private final AliyunSmsProperties aliyunSmsProperties;

    @Autowired
    public UserManagementServiceImpl(
            IUserService userService,
            JwtUtil jwtUtil,
            CacheManager cacheManager,
            AliyunSmsProperties aliyunSmsProperties) {
        this.userService = userService;
        this.jwtUtil = jwtUtil;
        this.cacheManager = cacheManager;
        this.aliyunSmsProperties = aliyunSmsProperties;
    }

    @Override
    @WebLog
    @Cacheable(value = "token",key = "#user.account + ':' + #user.password",unless = "#result == null")
    public String login(User user) {
        User one = userService.getOne(new LambdaQueryWrapper<User>()
                .eq(User::getAccount, user.getAccount()));
        if(one != null && DataEncryption.matches(user.getPassword(),one.getPassword())){
            //生成token
            return jwtUtil.createToken(new HashMap<String, Object>(1) {{
                put("userId", one.getId());
            }});
        }else {
            throw new CustomException(CodeEnum.LOGIN_FAILED);
        }
    }

    @Override
    @WebLog
    @CachePut(value = "user",key = "#result.id",condition = "#result != null")
    public UserVO register(User user) {
        user.setIntroduction(defaultIntroduction);
        user.setAvatarUrl(defaultAvatarUrl);
        user.setPassword(DataEncryption.encode(user.getPassword()));
        User one = userService.getOne(new LambdaQueryWrapper<User>()
                .eq(User::getName, user.getName()).or()
                .eq(User::getAccount, user.getAccount()).or()
                .eq(User::getPhoneNumber, user.getPhoneNumber()));
        if(one == null && userService.save(user)){
            return new UserVO(user);
        }else {
            throw new CustomException(CodeEnum.OPERATION_FAILED);
        }
    }

    @Override
    @WebLog
    @Cacheable(value = "userToken",key = "T(com.lhh.springcommon.interceptor.JwtInterceptor).userIdFromThreadLocal",unless = "#result == null")
    public UserVO getUserByToken() {
        //获取userId
        Integer userId = JwtInterceptor.getUserIdFromThreadLocal();

        //从数据库查询
        User one = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getId, userId));
        if(one != null){
            return new UserVO(one);
        }else {
            throw new CustomException(CodeEnum.TOKEN_VERIFICATION_FAILED);
        }

    }

    @Override
    @WebLog
    @Cacheable(value = "phoneNumber",key = "#phoneNumber")
    public String sms(String phoneNumber) throws Exception {
        boolean matches = phoneNumber.matches("^1[3-9]\\d{9}$");
        if(!matches){
            //手机号码格式不正确
            throw new CustomException(CodeEnum.PHONE_NUMBER_FORMAT_ERROR);
        }else {
            return SendSms.createSendSms(phoneNumber,
                    aliyunSmsProperties.getMaxNumber(),
                    aliyunSmsProperties.getAccessKey(),
                    aliyunSmsProperties.getSecretKey());
        }
    }

    @Override
    @WebLog
    @Cacheable(value = "token",key = "#phoneNumber + '+' + #code",unless = "#result == null")
    public String smsLogin(String phoneNumber, String code) {
        Cache phoneNumberCache = cacheManager.getCache("phoneNumber");
        if(phoneNumberCache == null || phoneNumberCache.get(phoneNumber) == null || !phoneNumberCache.get(phoneNumber).get().toString().equals(code)){
            //验证码不正确
            throw new CustomException(CodeEnum.CODE_ERROR);
        }
        User one = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getPhoneNumber, phoneNumber));
        if(one != null){
            //生成token
            return jwtUtil.createToken(new HashMap<String, Object>(1) {{
                put("userId", one.getId());
            }});
        }else{
            throw new CustomException(CodeEnum.PHONE_NUMBER_NOT_EXISTS);
        }
    }

    @Override
    @WebLog
    public Boolean checkNoRepeat(String key, String value) {
        if(key == null || value == null){
            throw new CustomException(CodeEnum.OPERATION_FAILED);
        }
        switch (key){
            case "name":
                return userService.getOne(new LambdaQueryWrapper<User>().eq(User::getName, value)) == null;
            case "account":
                return userService.getOne(new LambdaQueryWrapper<User>().eq(User::getAccount, value)) == null;
            case "phoneNumber":
                return userService.getOne(new LambdaQueryWrapper<User>().eq(User::getPhoneNumber, value)) == null;
            default:
                return false;
        }
    }

    @Override
    @WebLog
    @Cacheable(value = "getUserVOByUser",key = "#user.id",unless = "#result == null")
    public UserVO getUserVOByUser(User user) {
        User one = userService.getOne(new LambdaQueryWrapper<User>()
                .eq(user.getId() != null, User::getId, user.getId())
                .eq(user.getName() != null, User::getName, user.getName())
                .eq(user.getAccount() != null, User::getAccount, user.getAccount())
                .eq(user.getPhoneNumber() != null, User::getPhoneNumber, user.getPhoneNumber())
                .eq(user.getPassword() != null, User::getPassword, user.getPassword())
                .eq(user.getAvatarUrl() != null, User::getAvatarUrl, user.getAvatarUrl())
                .eq(user.getIntroduction() != null, User::getIntroduction, user.getIntroduction()));
        return new UserVO(one);
    }

}
